package com.yeyks.commonReference.service.mattress.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.ImmutableMap;
import com.yeyks.account.dal.domain.AccountInfo;
import com.yeyks.account.utils.AccountUtil;
import com.yeyks.common.base.Arguments;
import com.yeyks.common.constants.AccountType;
import com.yeyks.common.em.accountinfo.AccountInfoTypeEnum;
import com.yeyks.common.em.mattress.HotelMattressBillEnum;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.commonReference.service.account.AccountInfoService;
import com.yeyks.commonReference.service.hotel.HotelInfoService;
import com.yeyks.commonReference.service.mattress.HotelMattressOverviewService;
import com.yeyks.hotel.dal.domain.HotelInfo;
import com.yeyks.mattress.dal.domain.HotelMattressBill;
import com.yeyks.mattress.dal.domain.HotelMattressOverview;
import com.yeyks.mattress.dal.dao.HotelMattressOverviewMapper;
import com.yeyks.mattress.service.HotelMattressBillService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;


/**
 * <p>
 * 酒店床垫分成总览表 服务实现类
 * </p>
 *
 * @author yun
 * @since 2019-07-16
 */
@Service
@Slf4j
public class HotelMattressOverviewServiceImpl extends ServiceImpl<HotelMattressOverviewMapper, HotelMattressOverview> implements HotelMattressOverviewService {

    @Autowired
    private HotelMattressBillService billService;
    @Autowired
    private HotelInfoService hotelInfoService;
    @Autowired
    private AccountInfoService accountInfoService;

    /**
     * 获取酒店共享床垫账户
     *
     * @param accountId
     * @return
     */
    @Override
    public HotelMattressOverview selectByHotelId(Integer accountId) {
        if (null == accountId) {
            throw new ServiceException("酒店账户id不能为空");
        }
        HotelMattressOverview overview = baseMapper.selectOne(new QueryWrapper<HotelMattressOverview>().eq(HotelMattressOverview.ACCOUNT_ID, accountId));
        if (null == overview) {
            return getHotelMattressOverview(accountId, AccountInfoTypeEnum.HotelManager.value());
        }
        return overview;
    }

    /**
     * 获取酒店共享床垫账户
     *
     * @param accountId
     * @param accountType
     * @return
     */
    @Override
    public HotelMattressOverview selectByAccountId(Integer accountId, Integer accountType) {
        Arguments.intIsNull(accountId, "账户id不能为空");
        HotelMattressOverview overview = baseMapper.selectOne(new QueryWrapper<HotelMattressOverview>()
                .eq(HotelMattressOverview.ACCOUNT_ID, accountId)
                .eq(HotelMattressOverview.ACCOUNT_TYPE, accountType));
        if (null == overview) {
            return getHotelMattressOverview(accountId, accountType);
        }
        return overview;
    }

    private HotelMattressOverview getHotelMattressOverview(Integer accountId, Integer accountType) {
        HotelMattressOverview overview = new HotelMattressOverview();
        overview.setAccountId(accountId);
        overview.setAccountType(accountType);
        overview.setOutAmount(0);
        overview.setRemainAmount(0);
        overview.setTotalFeeAmount(0);
        overview.setTotalInAmount(0);
        Date date = new Date();
        overview.setCreateTime(date);
        overview.setUpdateTime(date);
        baseMapper.insert(overview);
        return overview;
    }

    /**
     * 共享床垫订单
     *
     * @param accountId        账户id
     * @param accountType      账户类型
     * @param orderNo          订单号
     * @param totalAmount      订单总金额
     * @param commissionAmount 分成金额
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(Integer accountId, Integer accountType, String orderNo, Integer totalAmount, Integer commissionAmount) {
        Arguments.intIsNull(totalAmount, "订单总金额不能为空");
        Arguments.intLtZero(totalAmount, "订单总金额不能小于0");
        Arguments.intEqualZero(totalAmount, "订单总金额不能为0");
        if (null == commissionAmount || commissionAmount < 0) {
            commissionAmount = 0;
        }
        HotelMattressOverview overview = selectByAccountId(accountId, accountType);
        Arguments.beanIsNull(overview, "账户id不能为空");
        Date date = new Date();
        overview.setTotalInAmount(overview.getTotalInAmount() + totalAmount);
        overview.setTotalFeeAmount(overview.getTotalFeeAmount() + commissionAmount);
        overview.setRemainAmount(overview.getRemainAmount() + commissionAmount);
        overview.setUpdateTime(date);
        if (baseMapper.updateById(overview) != 1) {
            throw new ServiceException("修改床垫账户表异常");
        }
        //写入账户明细表信息
        insertHotelMattressBill(date, accountId, accountType, HotelMattressBillEnum.Remark.COMPLATE.desc(), HotelMattressBillEnum.Type.IN.value(), commissionAmount, orderNo);
        return true;
    }

    /**
     * 提现申请被驳回或打款失败，账户金额回退
     *
     * @param orderNo 提现订单号
     * @param remark  备注
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(String orderNo, String remark) {
        if (Arguments.strIsNull(orderNo)) {
            log.info("提现订单驳回账户金额添加失败，提现订单号为空orderNo = {}", orderNo);
            throw new ServiceException("提现订单号为空");
        }
        HotelMattressBill bill = billService.getOne(new QueryWrapper<HotelMattressBill>()
                .eq(HotelMattressBill.BIZ_NO, orderNo)
                .eq(HotelMattressBill.TYPE, HotelMattressBillEnum.Type.OUT.value())
                .eq(HotelMattressBill.REMARK, HotelMattressBillEnum.Remark.SUCCESS.desc()));
        if (null == bill) {
            log.info("提现订单驳回账户金额添加失败，提现订单未找到orderNo = {}", orderNo);
            throw new ServiceException("该提现订单明细不存在");
        }
        Date date = new Date();
        HotelMattressOverview overview = selectByHotelId(bill.getAccountId());
        if (null == overview) {
            log.info("提现订单驳回账户金额添加失败，提现订单查询酒店床垫账户未找到orderNo = {}", orderNo);
            throw new ServiceException("酒店id不能为空");
        }
        overview.setOutAmount(overview.getOutAmount() - bill.getOperatorAmount());
        overview.setRemainAmount(overview.getRemainAmount() + bill.getOperatorAmount());
        overview.setUpdateTime(date);
        if (baseMapper.updateById(overview) != 1) {
            throw new ServiceException("修改床垫账户表异常");
        }
        //写入账户明细表信息
        insertHotelMattressBill(date, bill.getAccountId(), bill.getAccountType(), remark, HotelMattressBillEnum.Type.IN.value(), bill.getOperatorAmount(), orderNo);
        return true;
    }

    /**
     * 提现
     *
     * @param accountId      账户id
     * @param operatorAmount 提现金额
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean desc(Integer accountId, Integer operatorAmount, String orderNo) {
        Arguments.intIsNull(operatorAmount, "提现金额不能为空");
        Arguments.intLtZero(operatorAmount, "提现金额不能小于0");
        Arguments.intEqualZero(operatorAmount, "提现金额不能不能为0");
        HotelMattressOverview overview = selectByAccountId(accountId, AccountInfoTypeEnum.HotelManager.value());
        Arguments.beanIsNull(overview, "账户id不能为空");
        if (null == overview.getRemainAmount() || overview.getRemainAmount() < operatorAmount) {
            throw new ServiceException("账户金额不足");
        }
        Arguments.isTrue(!operatorAmount.equals(overview.getRemainAmount()), "必须全部提现");
        Date date = new Date();
        //首先修改账户总览表的数据
        overview.setOutAmount(overview.getOutAmount() + operatorAmount);
        overview.setRemainAmount(overview.getRemainAmount() - operatorAmount);
        overview.setUpdateTime(date);
        if (baseMapper.updateById(overview) != 1) {
            throw new ServiceException("修改床垫账户表异常");
        }
        AccountInfo accountInfo = accountInfoService.getById(accountId);
        //写入账户明细表信息
        insertHotelMattressBill(date, accountId, accountInfo.getType(), HotelMattressBillEnum.Remark.SUCCESS.desc(), HotelMattressBillEnum.Type.OUT.value(), operatorAmount, orderNo);
        return true;
    }

    /**
     * 获取床垫分佣账户余额
     *
     * @param loginUser
     * @return
     */
    @Override
    public Map<String, Object> remain(AccountInfo loginUser) {
        HotelMattressOverview overview = selectByAccountId(AccountUtil.getOperationUserId(loginUser), loginUser.getType());
        if (null == overview) {
            throw new ServiceException("该账户下酒店不存在");
        }
        String phone = loginUser.getPhone();
        if (AccountInfoTypeEnum.HotelManager.value().equals(loginUser.getType())) {
            HotelInfo hotelInfo = hotelInfoService.getOne(new QueryWrapper<HotelInfo>().eq(HotelInfo.OPERATOR_ID, AccountUtil.getOperationUserId(loginUser)));
            if (hotelInfo != null) {
                phone = hotelInfo.getPhone();
            }
        }
        return ImmutableMap.of("remain", overview.getRemainAmount(),
                "phone", phone,
                "totalInAmount", overview.getTotalInAmount());
    }

    private void insertHotelMattressBill(Date date, Integer accountId, Integer accountType, String remark, Integer type, Integer operatorAmount, String orderNo) {
        //写入账户明细表信息
        HotelMattressBill newBill = new HotelMattressBill();
        newBill.setCreateTime(date);
        newBill.setAccountId(accountId);
        newBill.setAccountType(accountType);
        newBill.setRemark(remark);
        newBill.setType(type);
        newBill.setOperatorAmount(operatorAmount);
        newBill.setBizNo(orderNo);
        if (!billService.save(newBill)) {
            throw new ServiceException("插入床垫账户明细异常");
        }
    }

}
